package cn.ratel.db;

import cn.ratel.kit.CollectionKit;
import cn.ratel.kit.StrKit;
import com.google.common.base.Preconditions;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

class Dialect {
	static String findById(Table table) {
		return String.format("select * from %s where id=?", table.name);
	}

	static SqlAndParams update(Table table, Map<String, Object> attrs, Set<String> modifiedAttrs) {
		Preconditions.checkArgument(CollectionKit.isNotEmpty(modifiedAttrs), "none column is changed");
		modifiedAttrs.remove("id");
		Preconditions.checkArgument(CollectionKit.isNotEmpty(modifiedAttrs), "none column is changed");
		String sql = "update " + table.name + " set ";
		for (String modifiedAttr : modifiedAttrs) {
			if ("id".equals(modifiedAttr)) {
				continue;
			}
			sql += modifiedAttr + "=? , ";
		}
		sql = sql.substring(0, sql.length() - 2) + "where id=?";

		List<Object> params = modifiedAttrs.stream().map(attrs::get).collect(Collectors.toList());
		params.add(attrs.get("id"));
		return new SqlAndParams(sql, params.toArray());
	}

	static String deleteById(Table table) {
		return String.format("delete from %s where id=?", table.name);
	}

	static SqlAndParams save(Table table, Map<String, Object> attrs) {
		if (attrs.get("id") == null || Integer.parseInt(attrs.get("id").toString()) == 0) {
			attrs.remove("id");
		}
		String sql = "insert into " + table.name + " ( ";
		String columns = "( ";
		for (String columnName : attrs.keySet()) {
			sql += columnName + " , ";
			columns += " ? , ";
		}
		columns = columns.substring(0, columns.length() - 2) + " ";
		sql = sql.substring(0, sql.length() - 2) + ") values " + columns + ")";

		Object[] params = attrs.keySet().stream().map(attrs::get).toArray();
		return new SqlAndParams(sql, params);
	}

	public static SqlAndParams find(Table table, Map<String, Object> attrs) {
		String sql = "select * from " + table.name + " where ";
		List<Object> params = new ArrayList<>();
		for (Map.Entry<String, Object> entry : attrs.entrySet()) {
			sql += entry.getKey() + "=? and ";
			params.add(entry.getValue());
		}
		sql = sql.substring(0, sql.length() - 5);
		return new SqlAndParams(sql, params.toArray());
	}

	static class SqlAndParams {
		String sql;
		Object[] params;

		SqlAndParams(String sql, Object[] params) {
			this.sql = sql;
			this.params = params;
		}
	}

	static String paginateList(String sql, int pageNumber, int pageSize) {
		Preconditions.checkArgument(StrKit.notBlank(sql) && "select".equals(sql.trim().substring(0, 6).toLowerCase()), "paginate sql must start with 'select'");
		sql = sql.trim().substring(6);
		return "select SQL_CALC_FOUND_ROWS " + sql + " limit " + pageNumber * pageSize + ", " + pageSize;
	}

	static String paginateCount() {
		return "select FOUND_ROWS() as totalRow";
	}

}
